#include "encoderprovidermgr.h"
#include "encoderinterface.h"

#include <QDir>
#include <QFileInfo>
#include <QFileInfoList>
#include <QLibrary>
#include <QFile>
#include <QPluginLoader>
#include "ldebug.h"

static EncoderProviderMgr * _instance = NULL;

typedef EncoderInterface * (* create_provider_func_t) (const QString &);

EncoderProviderMgr * EncoderProviderMgr::instance() {
    return _instance;
}

EncoderProviderMgr::EncoderProviderMgr(QObject *parent) :
    QObject(parent)
{
    _instance = this;
}

QList<EncoderInterface *> EncoderProviderMgr::allAvailableEncoderProviders() const {
    return m_installedEncoderProvider.values();
}

EncoderInterface * EncoderProviderMgr::encoderProvider(const QString & key) const {
    return m_installedEncoderProvider.value(key,NULL);
}

void EncoderProviderMgr::findAndRegisterProviders() {
    QString name;
    EncoderInterface *nprovider;
    EncoderInterface::Infomation provider_info;
    foreach(QString path, m_providerSearchPath) {
	QFileInfo info(path);
	if (!info.isDir() || !info.isReadable()) continue;

	QDir dir(path);
	QFileInfoList providers = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs);
	foreach (QFileInfo provider, providers){
	    QString path = provider.absoluteFilePath() + "/provider.plib";
	    QLibrary lib(path);
	    if (!lib.load()) {
		DBG->warn(lib.errorString().toLocal8Bit().constData());
		goto invalid_provider_out;
	    }

	    // Try to parse the dll for our entry
	    create_provider_func_t func;
	    func = (create_provider_func_t)lib.resolve("create_instance");
	    if (!func) {
		goto invalid_provider_out;
	    }

	    // Get the provider instance from DLL
	    nprovider = (EncoderInterface *)(func(provider.absoluteFilePath()));
	    if (!nprovider) {
		goto invalid_provider_out;
	    }

	    // Try to insert provider

	    provider_info = nprovider->infomation();
	    name = provider_info.name;
	    if (m_installedEncoderProvider.contains(name)) {
		DBG->warn("Provider library '%s' seems to have registered before\n",
			  path.toAscii().constData());
	    }
	    m_installedEncoderProvider[name] = nprovider;



	    continue;

	invalid_provider_out:
	    DBG->warn("Provider library '%s' looks like not a collect provider file\n",
		      path.toAscii().constData());
	    continue;
	}
    }
}
